Repository navigation
feat(core): Add longTaskIntegration to report JS long tasks as metrics - #6986
Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
🤖 This preview updates automatically when you update the PR. |
|
Replace the #XXXX placeholder in the CHANGELOG entry with the number of the pull request, #6986, now that the PR exists.
📲 Install BuildsAndroid
|
antonis
left a comment
There was a problem hiding this comment.
Left a couple of comments but overall the code changes LGTM 🚀
🔮 Next steps
Verify the metric in a sample app on React Native 0.82+ with the New Architecture, and document the integration on docs.sentry.io.
Let's do that now so that we can test e2e before shipping this and add a link in the description.
| return; | ||
| } | ||
|
|
||
| if (Math.random() >= sampleRate) { |
There was a problem hiding this comment.
q: Why a sample rate for this metric when metrics by default doesnt have a sample rate?
There was a problem hiding this comment.
The issue (#6185) asks for a configurable sample rate. The customer wants this across a large fleet, and the option lets them cut volume and the on-device work. The SDK decides once per launch, so a sampled launch reports all its long tasks, and filtering by user still shows a full picture. The JSDoc says that Sentry does not scale the counts by this rate. Users can also drop metrics in beforeSendMetric, so I can remove the option if we prefer fewer knobs.
| return; | ||
| } | ||
|
|
||
| if (Math.random() >= sampleRate) { |
There was a problem hiding this comment.
q: would there be any benefit in using import { _INTERNAL_safeMathRandom } from '@sentry/core'; here?
There was a problem hiding this comment.
I checked it, and it gives no benefit here. _INTERNAL_safeMathRandom only wraps Math.random() when a framework sets the __SENTRY_SAFE_RANDOM_ID_WRAPPER__ global, which is for server prerendering, for example in Next.js. React Native never sets it so the call is plain Math.random(). The profiling integration in this SDK also uses Math.random() for sampling.
Stall tracking only records JS thread blocking inside an active transaction, so blocking outside of traced work stays invisible. The new opt-in longTaskIntegration listens to the React Native PerformanceObserver for 'longtask' entries and sends each task of at least minDurationMs (default 200 ms) as the react_native.long_task.duration distribution metric. It does not depend on tracing. Scope attributes and the user come from the metrics pipeline in @sentry/core, so apps can filter by their own attributes. sampleRate (default 1) is checked once per launch, so a sampled launch reports all its long tasks. The observer uses buffered: true to also report tasks from before Sentry.init, and disconnects when the client closes. React Native installs PerformanceObserver with 'longtask' support only from 0.82 on the New Architecture, and fixes the native threshold at 50 ms. In other environments the integration logs a debug message and does nothing.
Replace the #XXXX placeholder in the CHANGELOG entry with the number of the pull request, #6986, now that the PR exists.
…ection longTaskIntegration now returns early when enableMetrics is false. @sentry/core already drops the metrics in that case, but the observer still ran on the device for nothing. The support check now runs inside the try/catch. Reading the lazy PerformanceObserver global loads the React Native module, and supportedEntryTypes calls into native code, so both can throw. An error there now logs a debug warning instead of breaking client setup.
52776ac to
d30d70a
Compare
Co-authored-by: Markus Hintersteiner <markus.hintersteiner@sentry.io>
Co-authored-by: Markus Hintersteiner <markus.hintersteiner@sentry.io>
* feat(core): Add longTaskIntegration to report JS long tasks as metrics Stall tracking only records JS thread blocking inside an active transaction, so blocking outside of traced work stays invisible. The new opt-in longTaskIntegration listens to the React Native PerformanceObserver for 'longtask' entries and sends each task of at least minDurationMs (default 200 ms) as the react_native.long_task.duration distribution metric. It does not depend on tracing. Scope attributes and the user come from the metrics pipeline in @sentry/core, so apps can filter by their own attributes. sampleRate (default 1) is checked once per launch, so a sampled launch reports all its long tasks. The observer uses buffered: true to also report tasks from before Sentry.init, and disconnects when the client closes. React Native installs PerformanceObserver with 'longtask' support only from 0.82 on the New Architecture, and fixes the native threshold at 50 ms. In other environments the integration logs a debug message and does nothing. * docs(core): Link longTaskIntegration changelog entry to its PR Replace the #XXXX placeholder in the CHANGELOG entry with the number of the pull request, #6986, now that the PR exists. * fix(core): Skip long task observer when metrics are off and guard detection longTaskIntegration now returns early when enableMetrics is false. @sentry/core already drops the metrics in that case, but the observer still ran on the device for nothing. The support check now runs inside the try/catch. Reading the lazy PerformanceObserver global loads the React Native module, and supportedEntryTypes calls into native code, so both can throw. An error there now logs a debug warning instead of breaking client setup. * chore: Add longTaskIntegration to the React Native sample Enable longTaskIntegration with a 100 ms threshold and add a button on the Performance screen that blocks the JS thread for 300 ms, so the react_native.long_task.duration metric can be tested end to end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Alexander Pantiukhov <alex@apantiukhov.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
📢 Type of change
📜 Description
Adds the opt-in
longTaskIntegration. It listens to the React NativePerformanceObserverforlongtaskentries and sends each task of at leastminDurationMs(default 200 ms) as thereact_native.long_task.durationdistribution metric, without an active transaction.sampleRate(default 1) is checked once per app launch, and the integration does nothing where long tasks are not supported (Old Architecture, React Native below 0.82).💡 Motivation and Context
Stall tracking only records JS thread blocking inside a transaction, so customers cannot see blocking across their fleet. Metrics carry the scope attributes and user from
@sentry/core, so apps can filter by their own attributes. Closes #6185.💚 How did you test it?
Unit tests with a fake
PerformanceObservercover the threshold, sampling, unsupported environments,observe()errors, and disconnect on client close. I have not run it on a device yet.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
Verify the metric in a sample app on React Native 0.82+ with the New Architecture, and document the integration on docs.sentry.io.